package org.inspursc.s0517.health.common.security;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.inspursc.s0517.health.common.dao.SysGroupRoleDao;
import org.inspursc.s0517.health.common.dao.SysPermissionDao;
import org.inspursc.s0517.health.common.dao.SysPermissionGroupDao;
import org.inspursc.s0517.health.common.dao.SysRoleDao;
import org.inspursc.s0517.health.common.entity.SysGroupRole;
import org.inspursc.s0517.health.common.entity.SysPermission;
import org.inspursc.s0517.health.common.entity.SysPermissionGroup;
import org.inspursc.s0517.health.common.entity.SysRole;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Service
@Slf4j
public class MyInvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource {

    @Autowired
    private SysPermissionDao permissionDao;

    @Autowired
    private SysRoleDao roleDao;

    @Autowired
    private SysGroupRoleDao groupRoleDao;

    @Autowired
    private SysPermissionGroupDao permissionGroupDao;

    private HashMap<String, Collection<ConfigAttribute>> map = null;

    /**
     * 加载权限表中所有权限
     */
    public void loadResourceDefine() {
        log.info("加载权限数据....");
        map = new HashMap<>();

        List<SysRole> roles = roleDao.findAll();

        for (SysRole role : roles) {

            List<SysGroupRole> permissionRoles = groupRoleDao.findBySysRoleId(role.getId());
            for (SysGroupRole groupRole : permissionRoles) {

                List<SysPermissionGroup> permissionGroupList = permissionGroupDao.findBySysGroupId(groupRole.getSysGroupId());

                permissionGroupList.forEach(permissionGroup -> {
                    Collection<ConfigAttribute> configAttributes = new ArrayList<>();
                    Optional<SysPermission> optionalSysPermission = permissionDao.findById(permissionGroup.getSysPermissionId());
                    SysPermission permission = optionalSysPermission.get();
                    if (StringUtils.isNotEmpty(permission.getUrl())) {
                        ConfigAttribute configAttribute = new SecurityConfig(role.getName());
                        if (map.containsKey(permission.getUrl())) {
                            configAttributes = map.get(permission.getUrl());
                            configAttributes.add(configAttribute);
                        } else {
                            configAttributes.add(configAttribute);
                        }
                        map.put(permission.getUrl(), configAttributes);
                    }
                });


            }

        }
    }

    //此方法是为了判定用户请求的url 是否在权限表中，如果在权限表中，则返回给 decide 方法，用来判定用户是否有此权限。如果不在权限表中则放行。
    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        //object 中包含用户请求的request 信息
        HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
        String url = request.getRequestURI();
        if (map == null) {
            loadResourceDefine();
        }
        if (url.startsWith("/api")) {
            AntPathRequestMatcher matcher;
            String resUrl;
            for (Iterator<String> iter = map.keySet().iterator(); iter.hasNext(); ) {
                resUrl = iter.next();
                if (StringUtils.isNotEmpty(resUrl)) {
                    matcher = new AntPathRequestMatcher(resUrl);
                    if (matcher.matches(request)) {
                        return map.get(resUrl);
                    }
                }
            }
            return SecurityConfig.createList("ROLE_401");
        }
        return null;
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}
